//; ---------------------------------------------------------------------------
//; Object 22 - Buzz Bomber enemy	(GHZ, MZ, SYZ)
//; ---------------------------------------------------------------------------

#include "buzzbomber.h"

#include "missile.h"
#include "../../sprite.h"
#include "../../objectsystemNEWER.h"

static object *obj;

#define player objects[0]
extern object *objects;

//; ---------------------------------------------------------------------------
//; Animation script - Buzz Bomber enemy
//; ---------------------------------------------------------------------------
byte fly1[4]  = {  1, 0, 1, afEnd };
byte fly2[4]  = {  1, 2, 3, afEnd };
byte fires[4] = {  1, 4, 5, afEnd };

byte *Ani_Buzz[3] = { fly1, fly2, fires };

//; ---------------------------------------------------------------------------
//; Sprite mappings - Buzz Bomber enemy
//; ---------------------------------------------------------------------------
byte Fly1[31] =   { 6,
		 0xF4, 9, 0,	   0, 0xE8,	//; flying
		 0xF4, 9, 0,	 0xF,    0, 
		    4, 8, 0,    0x15, 0xE8,
		    4, 4, 0,    0x18,    0,
		 0xF1, 8, 0,	0x1A, 0xEC,
		 0xF1, 4, 0,	0x1D,    4
};
byte Fly2[31] =	  { 6,
		 0xF4, 9, 0,	   0, 0xE8,
		 0xF4, 9, 0,	 0xF,    0,
		    4, 8, 0,    0x15, 0xE8,
		    4, 4, 0,    0x18,    0,
		 0xF4, 8, 0,	0x1F, 0xEC,
		 0xF4, 4, 0,	0x22,    4
};
byte Fly3[36] =   { 7,
		    4, 0, 0,    0x30,  0xC,
		 0xF4, 9, 0,	   0, 0xE8,
		 0xF4, 9, 0,	 0xF,    0,
		    4, 8, 0,    0x15, 0xE8,
		    4, 4, 0,    0x18,    0,
		 0xF1, 8, 0,	0x1A, 0xEC,
		 0xF1, 4, 0,	0x1D,    4
};
byte Fly4[36] =   { 7,
		    4, 4, 0, 0x31,  0xC,
		 0xF4, 9, 0,	0, 0xE8,
		 0xF4, 9, 0,  0xF,    0,
		    4, 8, 0, 0x15, 0xE8,
		    4, 4, 0, 0x18,    0,
		 0xF4, 8, 0, 0x1F, 0xEC,
		 0xF4, 4, 0, 0x22,    4
};
byte Fire1[31] =  { 6,
		 0xF4, 0xD, 0,    0, 0xEC,	//; stopping and firing
		    4, 0xC, 0,    8, 0xEC,
		    4,   0, 0,  0xC,  0xC,
		  0xC,   4, 0,  0xD, 0xF4,
		 0xF1,   8, 0, 0x1A, 0xEC,
		 0xF1,   4, 0, 0x1D,    4
};
byte Fire2[31] =  { 4,
		 0xF4, 0xD, 0,     0, 0xEC,
		    4, 0xC, 0,     8, 0xEC,
		    4,   0, 0,   0xC,  0xC,
		  0xC,   4, 0,   0xD, 0xF4,
		 0xF4,   8, 0,	0x1F, 0xEC,
		 0xF4,   4, 0,	0x22,    4
};

byte *Map_Buzz[6] = { Fly1, Fly2, Fly3, Fly4, Fire1, Fire2 };
//==========

void (*Buzz_Index[3])() = { Buzz_Main, Buzz_Action, Buzz_Delete };

//OBJECT:					; XREF: Obj_Index
void BuzzBomber(object *_obj)
{
    obj = _obj;

    //moveq	#0,d0
    //move.b	obRoutine(a0),d0
    byte routine = obj->Routine/2;

    //move.w	Buzz_Index(pc,d0.w),d1
    //jmp	Buzz_Index(pc,d1.w)
    (*Buzz_Index[routine])();
}

//; ===========================================================================

#define timedelay 0x32
#define buzzstatus 0x34
#define parent 0x3C

//OBJECT_Main:	; Routine 0
void Buzz_Main()
{
    //addq.b	#2,obRoutine(a0)
    obj->Routine = obj->Routine + 2;

    //move.l	#Map_Buzz,obMap(a0)
    obj->Map = Map_Buzz;

    //move.w	#$444,obGfx(a0)
    obj->Gfx = 0x444;

    //move.b	#4,obRender(a0)
    obj->Render = 4;

    //move.b	#3,obPriority(a0)
    obj->Priority = 3;

    //move.b	#8,obColType(a0)
    obj->ColType = 8;

    //move.b	#$18,obActWid(a0)
    obj->ActionWidth = 0x18;

    Buzz_Action();
}

void (*_index[2])() = { _move, chknearsonic };

//Buzz_Action:	; Routine 2
void Buzz_Action()
{
    //moveq	#0,d0
    //move.b	ob2ndRout(a0),d0
    byte secondRoutine = obj->secondRoutine/2;

    //move.w	@index(pc,d0.w),d1
    //jsr	@index(pc,d1.w)
    (*_index[secondRoutine])();

    //lea	(Ani_Buzz).l,a1
    byte **aniScript = Ani_Buzz;

    //bsr.w	AnimateSprite
    AnimateSprite(obj, aniScript);

    //bra.w	RememberState
    RememberState(obj);
}

//@move:					; XREF: @index
void _move()
{		
    //subq.w	#1,timedelay(a0) ; subtract 1 from time delay
    ptrsubobjvariableword(timedelay, obj, 1);

    
    //bpl.s	@noflip		; if time remains, branch
    if ((signed short)ptrgetobjvariableword(timedelay, obj) < 0)
    {
        //btst	#1,buzzstatus(a0) ; is Buzz Bomber near Sonic?
        //bne.s	@fire		; if yes, branch
        if ((obj->Variables[buzzstatus-0x28] & 2) == 0)
        {
	    //addq.b	#2,ob2ndRout(a0)
            obj->secondRoutine = obj->secondRoutine + 2;

	    //move.w	#127,timedelay(a0) ; set time delay to just over 2 seconds
            ptrsetobjvariableword(timedelay, obj, 127);

	    //move.w	#$400,obVelX(a0) ; move Buzz Bomber to the right
            obj->VelocityX = 0x400;

	    //move.b	#1,obAnim(a0)	; use "flying" animation
            obj->Anim = 1;

	    //btst	#0,obStatus(a0)	; is Buzz Bomber facing	left?
            //bne.s	@noflip		; if not, branch
            if ((obj->Status & 1) == 0)
            {
                //neg.w	obVelX(a0)	; move Buzz Bomber to the left
		obj->VelocityX = -obj->VelocityX;
            }
                
	    //@noflip:
	    //rts
        }
        else
        {	
            //@fire:
	    //bsr.w	FindFreeObj
            object *missile = FindFreeObj();

	    //bne.s	@fail
            if (missile->ID == 0)
            {
	        //move.b	#id_Missile,0(a1) ; load missile object
                missile->ID = id_Missile;
		
                //move.w	obX(a0),obX(a1)
                missile->X = obj->X;

		//move.w	obY(a0),obY(a1)
                missile->Y = obj->Y;

		//addi.w	#$1C,obY(a1)
                missile->Y = missile->Y + 0x1C;

		//move.w	#$200,obVelY(a1) ; move missile downwards
                missile->VelocityY = missile->VelocityY + 0x200;

		//move.w	#$200,obVelX(a1) ; move missile to the right
                missile->VelocityX = missile->VelocityX + 0x200;

		//move.w	#$18,d0
                signed short moveDist = 0x18;

		//btst	#0,obStatus(a0)	; is Buzz Bomber facing	left?
                //bne.s	@noflip2	; if not, branch
                if ((obj->Status & 1) == 0)
                {
		    //neg.w	d0
                    moveDist = -moveDist;

		    //neg.w	obVelX(a1)	; move missile to the left
                    missile->VelocityX = -missile->VelocityX;
                }

	        //@noflip2:
		//add.w	d0,obX(a1)
                missile->X = missile->X + moveDist;

		//move.b	obStatus(a0),obStatus(a1)
                missile->Status = obj->Status;

		//move.w	#$E,timedelay(a1)
                ptrsetobjvariableword(timedelay, missile, 0xE);

		//move.l	a0,parent(a1)
                ptrsetobjvariablelong(parent, missile, (long)&obj);

		//move.b	#1,buzzstatus(a0) ; set to "already fired" to prevent refiring
                obj->Variables[buzzstatus-0x28] = 1;

		//move.w	#$3B,timedelay(a0)
                ptrsetobjvariableword(timedelay, obj, 0x3B);

		//move.b	#2,obAnim(a0)	; use "firing" animation
                obj->Anim = 2;

	    }

            //@fail:
	    //rts
        }
    }
}   //; ===========================================================================

//@chknearsonic:				; XREF: @index
void chknearsonic()
{
    //subq.w	#1,timedelay(a0) ; subtract 1 from time delay
    ptrsubobjvariableword(timedelay, obj, 1);

    //bmi.s	@chgdirection
    if ((signed short)ptrgetobjvariableword(timedelay, obj) >= 0)
    {
        //bsr.w	SpeedToPos
        SpeedToPos(obj);

        //tst.b	buzzstatus(a0)
        //bne.s	@keepgoing
        if (obj->Variables[buzzstatus-0x28] == 0)
        {
	    //move.w	(v_player+obX).w,d0
            word playerX = player.X;

	    //sub.w	obX(a0),d0
            signed short distPlayerObj = playerX - obj->X;

	    //bpl.s	@isleft
            if (distPlayerObj < 0)
            {
		//neg.w	d0
                distPlayerObj = -distPlayerObj;
            }
	
            //@isleft:
	    //cmpi.w	#$60,d0		; is Buzz Bomber within	$60 pixels of Sonic?
            //bcc.s	@keepgoing	; if not, branch
            if (distPlayerObj < 0x60)
            {
		//tst.b	obRender(a0)
		//bpl.s	@keepgoing
		if ((signed char)obj->Render < 0)
                {
                    //move.b	#2,buzzstatus(a0) ; set Buzz Bomber to "near Sonic"
                    obj->Variables[buzzstatus-0x28] = 2;
              
		    //move.w	#29,timedelay(a0) ; set time delay to half a second
                    ptrsetobjvariableword(timedelay, obj, 29)
                
		    //bra.s	@stop
                    //@stop:
		    //subq.b	#2,ob2ndRout(a0)
		    obj->secondRoutine = obj->secondRoutine - 2;

                    //move.w	#0,obVelX(a0)	; stop Buzz Bomber moving
                    obj->VelocityX = 0;

		    //move.b	#0,obAnim(a0)	; use "hovering" animation
                    obj->Anim = 0;

                }
            }
        }
    }
    else
    {
        //; ===========================================================================
        //@chgdirection:
	//move.b	#0,buzzstatus(a0) ; set Buzz Bomber to "normal"
        obj->Variables[buzzstatus-0x28] = 0;

	//bchg	#0,obStatus(a0)	; change direction
        obj->Status = obj->Status ^ 1;

	//move.w	#59,timedelay(a0)
        ptrsetobjvariableword(timedelay, obj, 59)

	//@stop:
	//subq.b	#2,ob2ndRout(a0)
        obj->secondRoutine = obj->secondRoutine - 2;
 
	//move.w	#0,obVelX(a0)	; stop Buzz Bomber moving
        obj->VelocityX = 0;

        //move.b	#0,obAnim(a0)	; use "hovering" animation
        obj->Anim = 0;
    }

    //@keepgoing:
    //rts	
}   //; ===========================================================================

//Buzz_Delete:	; Routine 4
void Buzz_Delete()
{
    //bsr.w	DeleteObject
    DeleteObject(obj);
}	 
//rts	
